﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Configuration;
using Kratos.Framework.Filters;
using Kratos.Framework.Repositories;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

using Kratos.Framework.Configurations;
using Kratos.Framework.BootStrapTasks;
using Kratos.Framework.Infrastructures;
using Kratos.Framework.Repositories.NHibernateProvider;

namespace Kratos.Framework
{
    public class KratosMvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new KratosViewEngine());

            Application["unityContainer"] = SetupContainer();
            Application["bootStrapLoaded"] = false;
            Load();
        }

        private IUnityContainer SetupContainer()
        {
            //父容器注册基础实例
            var parentContainer = new UnityContainer();

            parentContainer
                .RegisterInstance((KratosConfigurationSection)ConfigurationManager.GetSection("kratos"))
                .RegisterInstance(RouteTable.Routes)
                .RegisterInstance(ModelBinders.Binders)
                .RegisterInstance(NHibernateConfiguration.Config.SingleSessionFactory);

            parentContainer
                .RegisterInstance<IBootStrapTasks>("LoadModules", new LoadModules(parentContainer));

            parentContainer
                .RegisterType<IModulesLoaded, ModulesLoaded>()
                .RegisterType<ISessionManager, SessionManager>()
                .RegisterType(typeof(IRepository<>), typeof(NHibernateRepository<>))
                .RegisterType<IRepositoryResolver, RepositoryResolver>()
                .RegisterType<IPerActionTransactionStore, PerActionTransactionStore>()
                .RegisterType<IFormsAuthentication, FormsAuthenticationWrapper>();


            parentContainer.RegisterInstance(typeof(UnitOfWorkFilter));

            var childContainer = parentContainer.CreateChildContainer();
            var unitySection = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;

            if (unitySection != null && unitySection.Containers.Default != null)
            {
                unitySection.Configure(childContainer);
            }
            childContainer.RegisterInstance(childContainer);

            return childContainer;
        }

        private void Load()
        {
            Load(new HttpContextWrapper(Context));
        }

        private static void Load(HttpContextBase context)
        {
            var container = context.Application["unityContainer"] as IUnityContainer;
            if (container == null)
                throw new Exception("Ioc容器没有绑定");
            IEnumerable<IBootStrapTasks> bootTasks = container.ResolveAll<IBootStrapTasks>();
            bool isLoaded = (bool)context.Application["bootStrapLoaded"];

            if (isLoaded)
            {
                foreach (var task in bootTasks)
                    task.CleanUp();
            }

            foreach (var task in bootTasks)
            {
                task.Execute();
            }

            context.Application["unityContainer"] = true;
        }
    }
}
